package com.bocloud.cmp.driver.providers.ali;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.ecs.model.v20140526.CreateDiskRequest;
import com.aliyuncs.ecs.model.v20140526.CreateDiskResponse;
import com.aliyuncs.ecs.model.v20140526.DeleteDiskRequest;
import com.aliyuncs.ecs.model.v20140526.DeleteDiskResponse;
import com.aliyuncs.ecs.model.v20140526.DescribeDisksRequest;
import com.aliyuncs.ecs.model.v20140526.DescribeDisksResponse;
import com.aliyuncs.ecs.model.v20140526.DescribeDisksResponse.Disk;
import com.aliyuncs.exceptions.ClientException;
import com.bocloud.cmp.driver.providers.VolumeDriver;
import com.bocloud.cmp.enums.VolumeCategory;
import com.bocloud.cmp.model.SnapshotModel;
import com.bocloud.cmp.model.VolumeModel;
import com.bocloud.common.model.BsmResult;
import com.bocloud.common.utils.DateTools;
import com.google.common.collect.Lists;

public class AliVolumeDriver extends AliDriver implements VolumeDriver {

	private static Logger logger = LoggerFactory.getLogger(AliVolumeDriver.class);

	public AliVolumeDriver() {
		super();
	}

	public AliVolumeDriver(String accessKey, String secretKey, String regionId) {
		super(accessKey, secretKey, regionId);
	}

	@Override
	public BsmResult list() {
		DescribeDisksRequest request = new DescribeDisksRequest();
		request.setPageNumber(1);
		request.setPageSize(100);
		List<VolumeModel> models = Lists.newArrayList();
		try {
			DescribeDisksResponse response = this.getClient().getAcsResponse(request);
			int totalCount = response.getTotalCount();
			List<Disk> disks = response.getDisks();
			for (Disk disk : disks) {
				models.add(convert(disk));
			}
			int totalPage = totalCount / 100 + 1;
			if (totalPage == 1) {
				return new BsmResult(true, models, "success");
			}
			for (int i = 2; i <= totalPage; i++) {
				request.setPageNumber(i);
				request.setPageSize(100);
				response = this.getClient().getAcsResponse(request);
				disks = response.getDisks();
				for (Disk disk : disks) {
					models.add(convert(disk));
				}
			}
			return new BsmResult(true, models, "success");
		} catch (ClientException e) {
			logger.error("list volumes error:", e);
			return new BsmResult(false, e.getErrCode(), e.getErrMsg());
		}
	}

	@Override
	public BsmResult create(VolumeModel volume) {
		CreateDiskRequest request = new CreateDiskRequest();
		request.setDiskName(volume.getName());
		request.setZoneId(volume.getZone());
		request.setDiskCategory(convertDiskCategory(volume.getCategory()));
		request.setDescription(volume.getRemark());
		request.setSize(volume.getSize());
		try {
			CreateDiskResponse response = this.getClient().getAcsResponse(request);
			BsmResult result = detail(response.getDiskId());
			if (result.isSuccess()) {
				VolumeModel model = (VolumeModel) result.getData();
				model.setRequestId(response.getRequestId());
				return new BsmResult(true, model, "success");
			} else {
				return result;
			}
		} catch (ClientException e) {
			logger.error("create volume {} error", JSONObject.toJSONString(volume), e);
			return new BsmResult(false, e.getErrCode(), e.getErrMsg());
		}
	}

	@Override
	public BsmResult remove(String volumeId) {
		DeleteDiskRequest request = new DeleteDiskRequest();
		request.setDiskId(volumeId);
		try {
			DeleteDiskResponse response = this.getClient().getAcsResponse(request);
			return new BsmResult(true, response.getRequestId());
		} catch (ClientException e) {
			logger.error("remove disk [{}]", volumeId, e);
			return new BsmResult(false, e.getErrCode(), e.getErrMsg());
		}
	}

	@Override
	public BsmResult detail(String volumeId) {
		BsmResult result = this.list();
		VolumeModel model = null;
		if (result.isSuccess()) {
			@SuppressWarnings("unchecked")
			List<VolumeModel> disks = (List<VolumeModel>) result.getData();
			for (VolumeModel disk : disks) {
				if (disk.getVolumeId().equals(volumeId)) {
					model = disk;
					break;
				}
			}
		}
		if (null == model) {
			return new BsmResult(false, "get volume detail error");
		} else {
			return new BsmResult(true, model, "success");
		}
	}

	private VolumeModel convert(Disk disk) {
		if (null == disk) {
			return null;
		}
		VolumeModel model = new VolumeModel();
		model.setSize(disk.getSize());
		model.setGmtCreate(DateTools.transfer("yyyy-MM-dd'T'HH:mmZ", disk.getCreationTime(), "Z"));
		model.setName(disk.getDiskName());
		model.setType(disk.getType().name());
		model.setStatus(disk.getStatus());
		model.setRemark(disk.getDescription());
		model.setVolumeId(disk.getDiskId());
		return model;
	}

	private String convertDiskCategory(String raw) {
		if (StringUtils.isEmpty(raw) || raw.equalsIgnoreCase("CLOUD")) {
			return "cloud";
		}
		if (raw.equalsIgnoreCase(VolumeCategory.EFFICIENCY.name())) {
			return "cloud_" + VolumeCategory.EFFICIENCY.name();
		}
		if (raw.equalsIgnoreCase(VolumeCategory.SSD.name())) {
			return "cloud_" + VolumeCategory.SSD.name();
		}
		return "cloud";
	}

	@Override
	public BsmResult modify(VolumeModel volume) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public BsmResult snapshot(SnapshotModel snapshotModel) {
		// TODO Auto-generated method stub
		return null;
	}
}
